#  dfcext = "DFC extension" version 0.1
#  is a lightweight wrapper to make DFC method calls a little easier on the developer
#  Currently the following interfaces are extended:
#  -- IDfTime
#  -- IDfCollection
#  -- IDfTypedObject
#  -- IDfSession
#  -- even base String class has one method to easy convert string to DfID objects
#
#NOTE:
#  The dfc classpath is loaded using a "dfc_cp.yaml" file that should sit in the same directory as the "dfcext.rb"
#TODO:
#1. read dfc.jar using yaml - done
#2. sess can get a read query
#3. sess can get a query in arrary format? need to set limit?
#4. do easy session transaction - did one but need to make it more robust.
#5. any other ideas?
#6. easly retreive text content?

require 'yaml'
require 'java'

#load classpath of dfc.jar when loading dfcext.rb file
dfc_cp = YAML::load_file 'dfc.yaml'
require dfc_cp["classpath"]




JavaUtilities.extend_proxy("com.documentum.fc.common.IDfTime") do
  #this method extends the *IDfTime* interface to do time comparision using the "==" rather than
  #using the compareTo method call
  def ==(obj)
     if  (self.compareTo(obj) == 0)
        true
     else
        false
     end
  end

  #this method extends the *IDfTime* interface to do time comparision using the "<" 
  #so obj1 < obj2 means that obj1 is an earlier time than obj2
  def <(obj)
     if (self.compareTo(obj) == -1) #self is earlier time than obj
        true
     else
        false
     end
  end

  #this method extends the *IDfTime* interface to do time comparision using the ">" 
  #so obj1 < obj2 means that obj1 is a older time than obj2
  def >(obj)
     if (self.compareTo(obj) == 1) #self is older time than obj
        true
     else
        false
     end
  end

end

JavaUtilities.extend_proxy("com.documentum.fc.client.IDfCollection") do
   
   # this method extends the *IDfCollection* interface so that the developer
   # can easily get the results especially in a query situation using a similar
   # *each* style on each result row
   def each_row
      if (self.getState == 1)
          while self.next
             yield self.getTypedObject
          end
      else
          raise "collection is not in ready state"
      end
   end
end





JavaUtilities.extend_proxy("com.documentum.fc.client.IDfTypedObject") do



#puts self.name
#puts self.methods

AttrTypeRef = {} 
AttrTypeRef[com.documentum.fc.common.IDfAttr::DM_BOOLEAN] = "Boolean"
AttrTypeRef[com.documentum.fc.common.IDfAttr::DM_INTEGER] = "Integer"
AttrTypeRef[com.documentum.fc.common.IDfAttr::DM_STRING] = "String"
AttrTypeRef[com.documentum.fc.common.IDfAttr::DM_ID] = "Id"
AttrTypeRef[com.documentum.fc.common.IDfAttr::DM_TIME] = "Time"
AttrTypeRef[com.documentum.fc.common.IDfAttr::DM_DOUBLE] = "Double"


   #the method missing if for the *IDfTypedObject* so that the developer can easily read and write attributes.
   #currently one problem is with common attributes like Title, Subject, Keywords, Authors, you cannot use this magic
   #however it will work if the custom types like a sub-class of dm_document e.g. abc_doc has a single string attribute like
   #mytitle can easily do the following:
   #  1. reading: abc_doc.mytitle
   #  2. writing: abc_doc.mytitle = "hellow world"
   #
   #for repeating attributes a read will return an array while if you want to write then pass in an array 
   def method_missing(sym, *args)
      possAtr = sym.to_s
      #puts "sym: #{possAtr}"
      #puts sym.class
      if (args.length > 0 )
         #puts "args: #{args.to_s}"
         #puts args.class
      end
     
      if (self.hasAttr(possAtr))
         if (self.isAttrRepeating(possAtr))
             puts "is repeating attr"
             #retreive the values as an Array
             valueCount = self.getValueCount possAtr
             return "" unless valueCount > 0
             values = []
             for num in (0..(valueCount -1))
                 #puts num
                 x = self.send "getRepeating#{AttrTypeRef[self.getAttrDataType(possAtr)]}", possAtr, num
                 values << x
             end
             values
         else
             #puts 'sending'
             self.send "get#{AttrTypeRef[self.getAttrDataType(possAtr)]}", possAtr
         end
      else
         if (/.=$/.match possAtr) then #matches the string 'method_call='
             #puts "possible assignment method #{possAtr}"
             possAtr.chop!
             if (self.hasAttr(possAtr))
                if (self.isAttrRepeating(possAtr))
                   replaceRepeating(possAtr, args[0])
                else
                   self.send "set#{AttrTypeRef[self.getAttrDataType(possAtr)]}", possAtr, args[0]
                end
             else
                raise ScriptError, "method missing or no such attribute to set"
             end
         else
            raise ScriptError, "method missing or no such attribute"
         end
      end

   end
 
   def replaceRepeating( attributeName, valuesArray)

         self.truncate attributeName, 0
         valuesArray.each { |value| self.send "append#{AttrTypeRef[self.getAttrDataType(attributeName)]}", attributeName, value }
   end



end

JavaUtilities.extend_proxy("com.documentum.fc.client.IDfSysObject") do

   def removeStandardAttributeHelper()
       
        self.class.send 'remove_method', 'keywords'
        self.class.send 'remove_method', 'getKeywords'
        self.class.send 'remove_method', 'setKeywords'
        self.class.send 'remove_method', 'authors'
        self.class.send 'remove_method', 'getAuthors'
        self.class.send 'remove_method', 'setAuthors'
   end

end


JavaUtilities.extend_proxy("com.documentum.fc.client.IDfSession") do

   #extends the *IDfSession* interface to have a easy way to do transaction
   def easy_transaction()
      begin
         if self.isTransactionActive() 
            raise "Transaction is active, cannot proceed"
         end
         startedHere = true
         self.beginTrans()
         #puts "beginTrans"
         retvalue = yield
         self.commitTrans()
         ["success", retvalue]
         #puts "commitTrans"
      rescue Exception => e
         puts "Transaction went into abortion"
         if (startedHere && self.isTransactionActive())
            self.abortTrans()
         end
         puts e.message
         ["failure", e.message]  
      # puts e.backtrace.inspect  
      end

   end

   #a new query method enhancing on the *getObjectsByQuery* method
   #user only needs to supply the from part like 'from dm_document'
   def getObjectsByQueryEnhanced(dql)
       temparr = dql.split(' ')
       self.getObjectsByQuery("select r_object_id, r_object_type, r_aspect_name, i_vstamp, i_is_reference, i_is_replica " + dql, temparr[1])
   end

end


class String
   #adds a new method to String class so that can convert from string to DfId
   def toDfId
      x = com.documentum.fc.common.DfId.new self.to_s
      return x
   end

end

RDfId = com.documentum.fc.common.DfId
#monkey patch the class
#todo: proxy extend the interface instead
class RDfId
   #open up the class to add to_s function
   def to_s
      x = self.toString
      return x
   end

   def +(obj)
      if obj.respond_to?("to_s") then
         self.to_s << obj.to_s
      else
         raise "cannot convert arg to string object in order to concat"
      end
   end   
end
